#ifndef SHAREDTABLEINPUTBOX_H_JM_20121205
#define SHAREDTABLEINPUTBOX_H_JM_20121205
/// @file SharedTableInputBox.h
/// 

// ##
#include "InputBox.h"
#include "DataProvider.h"
#include "../../LogConf.h"

#include "../../common_bbx/tables/BoxDataTable.h"
#include "../../common_bbx/tables/DataExportTarget.h"

#include "../../common_bbx/sharedBoxData/BinaryOperationArguments.h"

// ## c++
#include <type_traits>

namespace jm4bbx {

	template<class DataProviderImplT>
	class  SharedTableInputBox : public InputBox , public DataExportTarget {
		JM_USE_LOGGER(boxes_input_sharedTableInputBox_logger)
	public:		
		static const char* KEY_COLUMN_INDEX_PARAM_NAME;
		static const char* FIRST_OPERATION_ARGUMENT_PARAM_NAME;

		typedef DataProviderImplT DataProviderImpl;

		static_assert(std::is_base_of<DataProvider, DataProviderImpl>::value, 
			"SharedTableInputBox<T>: Template parameter has to implement interface DataProvider!");
		

		SharedTableInputBox(const BoxParamPack& p) 
			: InputBox(p), first_(false) {				
				keyColumnIndex_ = getBoxParameterValue(p, 
					KEY_COLUMN_INDEX_PARAM_NAME, 0);
	
				first_ = getBoxBoolParameterValue(p, 
					FIRST_OPERATION_ARGUMENT_PARAM_NAME, false);


				DataProviderImpl provider;
				provider.loadData(inputSpecification_, getTable());
		}

		virtual ~SharedTableInputBox() { }

		virtual void setData(const size_t col, const size_t row, 
			const int v) override {
				if (col == keyColumnIndex_) {
					LOG_T("index="<< row << " value="<< v)
					setData<IntegerKeyRecordPolicyType>(row, 
						IntegerKeyRecord(row, v));

				}
		}

		virtual void setData(const size_t col, const size_t row, 
			const std::string v)override {
				if (col == keyColumnIndex_) {
					LOG_T("index="<< row << " value="<< v)
					setData<StringKeyRecordPolicyType>(row, 
						StringKeyRecord(row, v));
				}
		}

		virtual size_t getColumnSize() const {
			if (!getTable()->isEmpty()) {
				// vsetky stlpce su rovnako velke
				return getTable()->getColumn(0)->getCellCount();
			}
			else {
				return 0;
			}
		};
	protected:
		virtual void loadData() {
			exportData(getTable(), this);
		}

		/**
		 * Nastavenie hodnoty do dat boxu.
		 * @param rowIndex index riadku do ktoreho sa ma vlozit hodnota
		 * @param value vkaldana hodnota
		 * 
		 * @tparam policy politika zodpovedajuca vkaldanemu typu
		 * @tparam T typ vkladanej hodnoty - musi zodpovedat typu cielovej bunky
		 **/
		template<class policy, class T>
		void setData(const size_t rowIndex, T value) {
			using namespace bobox;			
			get_data<policy>(OUTPUT_COLUMN)[rowIndex] = value;
		}
	private:
		int keyColumnIndex_;
		bool first_;

		BoxDataTable* getTable() {
			BoxDataTable* table;
			if (first_) {
				 table = BinaryOperationArguments<BoxDataTable>::getFirstArgument();
			}
			else {
				table = BinaryOperationArguments<BoxDataTable>::getSecondArgument();
			}
			return table;
		}

		const BoxDataTable* getTable() const {
			const BoxDataTable* table;
			if (first_) {
				table = BinaryOperationArguments<BoxDataTable>::getFirstArgument();
			}
			else {
				table = BinaryOperationArguments<BoxDataTable>::getSecondArgument();
			}
			return table;
		}
	};

	template<class T>
	const char* SharedTableInputBox<T>::FIRST_OPERATION_ARGUMENT_PARAM_NAME = 
		"first_op_arg";

	template<class T>
	const char* SharedTableInputBox<T>::KEY_COLUMN_INDEX_PARAM_NAME = 
		"key_column";

} // namespace jm4bbx


#endif
